package com.epoch.base.tag;

import org.beetl.core.*;
import org.beetl.core.exception.BeetlException;
import org.beetl.core.io.ByteWriter_Byte;
import org.beetl.core.io.ByteWriter_Char;
import org.beetl.core.statement.Statement;
import org.beetl.ext.tag.HTMLTagSupportWrapper;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;

public class HTMLTag extends HTMLTagSupportWrapper {

    HTMLTag parent = null;
    List<HTMLTag> children = null;
    Map<String, List<HTMLTag>> childrenMap = null;
    LinkedHashMap<String, Integer> binds = null;
    HttpServletRequest request;
    // 0 run ,1 known
    int status = 0;
    private static String VS = "BEETL_VISIT_STATUS";
    private static int RUN = 0;
    private static int VISIT = 1;
    Style style = null;
    String id;
    static int RID = 0;


    public void render() {

        if (status == RUN) {
            //渲染逻辑交给beetl脚本
            addThis();
            runTemplateTag();
            removeThis();
        } else {
            TagChildrenContext tnc = (TagChildrenContext) request.getAttribute("tagChildrenContext");
            tnc.getChildren().add(this);
            return;
        }


    }

    public void binds(Object[] arrays) {
        if (binds == null) {
            throw new UnsupportedOperationException("标签体未申明需要绑定变量");
        }
        Iterator<Integer> it = binds.values().iterator();
        int i = 0;
        while (it.hasNext()) {
            int index = it.next();
            this.ctx.vars[index] = arrays[i++];
        }
    }


    public String getBody() {
        try {
            return super.getBodyContent().toString();
        } catch (BeetlException ex) {
            ex.pushResource(this.ctx.getResourceId());
            throw ex;
        }


    }

    public BodyContent getExecute() {
        try {
            ByteWriter writer = ctx.byteWriter;
            ByteWriter tempWriter = ctx.byteWriter.getTempWriter(writer);
            ctx.byteWriter = tempWriter;
            runTemplateTag();
            ctx.byteWriter = writer;
            return tempWriter.getTempConent();
        } catch (BeetlException ex) {
            ex.pushResource(this.ctx.getResourceId());
            throw ex;
        }


    }

    public List<HTMLTag> getChildren() {
        if (children == null) {
            request.setAttribute(VS, this.VISIT);
            TagChildrenContext tnc = new TagChildrenContext();
            request.setAttribute("tagChildrenContext", tnc);
            visitChild();
            request.removeAttribute(VS);
            children = tnc.getChildren();
            childrenMap = tnc.getChildrenMap();
        }

        return children;
    }

    public Map<String, List<HTMLTag>> getChildrenMap() {
        return childrenMap;
    }

    public List<String> getMobile() {
        String str = (String) get("mobile");
        if (str == null) return Collections.EMPTY_LIST;
        return Arrays.asList(str.split(" "));
    }

    /**
     * 标签名
     *
     * @return
     */
    public String getTagName() {
        return (String) this.args[0];
    }

    public Map getAttrs() {
        Map map = (Map) this.args[1];
        return map;
    }

    public Object get(String attr) {
        if (this.args.length == 1) {
            return null;
        }
        Map map = (Map) this.args[1];
        if (map == null) return null;
        return map.get(attr);
    }


    public void init(Context ctx, Object[] args, Statement st) {
        super.init(ctx, args, st);
        request = (HttpServletRequest) this.ctx.getGlobal("request");
        Object temp = request.getAttribute(VS);
        this.status = temp == null ? 0 : (Integer) temp;


    }

    protected void setBinds(LinkedHashMap<String, Integer> binds) {
        this.binds = binds;
    }

    protected void visitChild() {


        ByteWriter tempWriter = null;
        if (gt.getConf().isDirectByteOutput()) {
            tempWriter = new ByteWriter_Byte(new NoLockEmptyByteArrayOutputStream(), gt.getConf().getCharset(), ctx);
        } else {
            tempWriter = new ByteWriter_Char(new NoLockEmptyStringWriter(), gt.getConf().getCharset(), ctx);

        }

        ByteWriter realWriter = ctx.byteWriter;
        ctx.byteWriter = tempWriter;
        bs.execute(ctx);
        ctx.byteWriter = realWriter;


    }

    protected void runTemplateTag() {
        //初始化

        String child = (String) args[0];

        String path = getHtmlTagResourceId(child);

        Template t = null;

        t = gt.getTemplate(path, this.ctx.getResourceId());

        t.binding(ctx.globalVar);
        t.dynamic(ctx.objectKeys);

        t.binding("tag", this);
        try {
            t.renderTo(ctx.byteWriter);
        } catch (BeetlException ex) {
//			ex.pushResource(path);
            ex.pushToken(ex.token);
            throw ex;
        }

    }

    public String toString() {
        return this.args[0] + ":" + super.toString();
    }


    public boolean isMobileEnable() {
        String mobile = (String) this.get("mobile");
        return mobile != null;
    }


    protected String getHtmlTagResourceId(String child) {
        String path = child.replace(':', File.separatorChar);
        StringBuilder sb = new StringBuilder("/");
        sb.append(this.tagRoot).append("/").append(path).append(".").append(this.tagSuffix);
        String key = sb.toString();
        ResourceLoader resourceLoader = gt.getResourceLoader();
        HttpServletRequest request = (HttpServletRequest) ctx.getGlobal("request");
        Boolean isMobile = (Boolean) request.getAttribute("isMobile");
        if (isMobile != null && isMobile) {
            String mobileKey = MobileUtil.genMobileKey(key);
            if (resourceLoader.exist(mobileKey)) {
                return mobileKey;
            } else {
                return key;
            }
        } else {
            return key;
        }

    }

    protected void addThis() {

        TagTree tree = (TagTree) request.getAttribute("tagTreeContext");
        if (tree == null) {
            tree = new TagTree();
            request.setAttribute("tagTreeContext", tree);
        }
        tree.addTag(this);
    }

    protected void removeThis() {
        TagTree tree = (TagTree) request.getAttribute("tagTreeContext");
        if (tree == null) return;
        tree.removeTag(this);
    }


    public HTMLTag getParent() {
        TagTree tree = (TagTree) request.getAttribute("tagTreeContext");
        if (tree == null) return null;
        return tree.getParenet(this);
    }

    public Style getStyle() {
        if (style != null) return style;
        style = new Style((String) this.get("style"));
        return style;
    }


    public String getRid() {
        if (this.id != null) return id;
        String id = (String) this.get("id");
        if (id != null) {
            this.id = id;
            return id;
        } else {
            this.id = this.getTagName() + "-" + randomId();
            return this.id;
        }
    }

    /**
     * 随机为标签产生一个id
     *
     * @return
     */
    private synchronized static int randomId() {
        if (RID < 1000000) {
            return RID++;
        } else {
            RID = 0;
            return RID;
        }
    }


}
